/*
 * HTTPHelper.java
 *
 * Created on March 23, 2005, 10:07 PM
 */

package http;

import driver.AppLog;
import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Document;
import org.w3c.tidy.Configuration;
import org.w3c.tidy.Tidy;

/**
 *
 * @author Keith
 */
public class HTTPHelper {
  
  final private static HTTPHelper instance = new HTTPHelper();
  
  final Logger myLogger = AppLog.appLog;
  
  private HTTPResponse getPageAsBytes( URL pageUrl, String auth ) throws MalformedURLException, URISyntaxException, IOException {
    
    char[] contents = null;
    
//    System.out.println( "pageUrl: " + pageUrl );
    long startTime = System.currentTimeMillis();
    
    HttpURLConnection hpcon = (HttpURLConnection) pageUrl.openConnection();

    try {
      hpcon.setConnectTimeout( 1000 * 30 );  // timeout after 30 secs.
      hpcon.setRequestProperty( "User-Agent", "Mozilla/4.0 (Compatible; MSIE 6.0; Windows NT 5.1)" );
      hpcon.setRequestProperty( "Content-Language", "en-US" );
      if ( auth == null ){
        hpcon.setRequestMethod( "GET" );
      hpcon.setRequestProperty("Content-Type", "text/html; charset=utf-8");
      } else {
        hpcon.setRequestMethod( "POST" );
        hpcon.setRequestProperty( "Content-Length", Integer.toString( auth.getBytes().length));
        hpcon.setRequestProperty( "Content-Type", "application/x-www-form-urlencoded" );
      }

      hpcon.setUseCaches( false );
      hpcon.setDoInput( true );
      HttpURLConnection.setFollowRedirects( false );
//      HttpURLConnection.setFollowRedirects( true );
      hpcon.setDoOutput( true );

      if ( auth != null ){
        DataOutputStream printout = new DataOutputStream (hpcon.getOutputStream ());
        printout.writeBytes( auth );
        printout.flush();
        printout.close();
      }
      int responseCd = hpcon.getResponseCode();
//System.out.println( "responseCd: " + responseCd );
      if ( responseCd == HttpURLConnection.HTTP_MOVED_TEMP ||
            responseCd == HttpURLConnection.HTTP_MOVED_PERM ){
        String location = hpcon.getHeaderField( "Location" );

        myLogger.log( Level.FINE, "redir location: " + location );
        HTTPResponse httpResponse = getPageAsBytes( new URL( pageUrl, location ), null );
        contents = httpResponse.getContents();
      } else {
//        System.out.println( "Response: " );
        myLogger.log( Level.FINE, "encoding: " + hpcon.getContentEncoding() );
        Reader is = new BufferedReader( new InputStreamReader(hpcon.getInputStream(), "utf-8") );
        CharArrayWriter os = new CharArrayWriter();
        char[] buff = new char[ 10000 ];
        int bytesRead;

        while ( ( bytesRead = is.read( buff ) ) != -1 ) {
          os.write( buff, 0, bytesRead );			
        }
        os.close();
        
        // process page
        contents = os.toCharArray();
// System.out.println( "<==== Content start ====>");
//        System.out.println( new String( contents ) );
// System.out.println( "<==== Content end ====>");
      }
    } finally {
      hpcon.disconnect();
    }

    HTTPResponse r = new HTTPResponse( System.currentTimeMillis() - startTime, contents );

    StringBuffer sb = new StringBuffer( pageUrl.toString() );
    final int maxLen = 80;
    if ( sb.length() > maxLen ){
      sb.setLength( maxLen - 3 );
      sb.append( "..." );
    } else {
      while ( sb.length() < maxLen ){
        sb.append( ' ' );
      }
    }
    myLogger.log( Level.FINE, sb.toString() + ", response: " + r.toString() );
    
    return r;
  }
  
  private Document tidyPage( InputStream htmlStream ){
    Tidy tidy = new Tidy();

//    tidy.setXHTML( true );
    tidy.setXmlPi( true );
    tidy.setXmlOut( true );
    tidy.setSmartIndent( true );
//    tidy.setShowWarnings( true );
//    tidy.setMakeClean( true );
    tidy.setMakeClean( false );
    tidy.setShowWarnings( false );
//    tidy.setQuiet( true );
    tidy.setQuiet( true );
    tidy.setWraplen( 120 );
//    PrintWriter pw = new PrintWriter( System.out );
//    tidy.setErrout( pw );
    tidy.setCharEncoding( Configuration.UTF8);
    tidy.setDropEmptyParas( true);
    tidy.setXmlTags( false );
    tidy.setTabsize( 1 );
//    tidy.setNumEntities(true);
    tidy.setNumEntities(false);

    return tidy.parseDOM( htmlStream, /*System.out */ null );
  }
  
  private Document getPageAsDom( URL pageUrl, String auth ) throws MalformedURLException, URISyntaxException, IOException {

    HTTPResponse response = getPageAsBytes( pageUrl, auth );
    char[] contents = response.getContents();
    
    String text = new String(contents, 0, contents.length);
    byte[] byteContent = text.getBytes("utf-8");
    
    InputStream htmlStream = new ByteArrayInputStream( byteContent );

    Document htmlDoc = tidyPage( htmlStream );
//XMLHelper.dump( htmlDoc );    
    return htmlDoc;
  }

  /** Creates a new instance of HTTPHelper */
  private HTTPHelper() {
    final CookieManager cm = new CookieManager(null,CookiePolicy.ACCEPT_ALL);
    CookieHandler.setDefault(cm);
  }
  
  static public HTTPHelper instance(){
    return instance;
  }
  
  static public Document getPage( URL pageUrl ) throws MalformedURLException, URISyntaxException, IOException {
    return instance.getPageAsDom( pageUrl, null );
  }
  
  static public char[] getPageContents( URL pageUrl ) throws MalformedURLException, URISyntaxException, IOException {
    return instance.getPageAsBytes( pageUrl, null ).getContents();
  }
  
  static public Document getPage( URL pageUrl, String auth ) throws MalformedURLException, URISyntaxException, IOException {
    return instance.getPageAsDom( pageUrl, auth );
  }
}
